const jwt = require('jsonwebtoken');
const errorTypes = require('../constants/error-types');
const service = require('../service/user.service');
const authService = require('../service/auth.service');
const md5password = require('../utills/password-handle');

const {
  PUBLIC_KEY
} = require('../app/config');


const verifyUser = async (ctx, next) => {
  //1.获取用户名和密码
  const {
    name,
    password
  } = ctx.request.body;


  //2.用户名和密码不能为空
  if (!name || !password) {
    const errorType = new Error(errorTypes.NAME_OR_PASSWORD_IS_REQUIRED);
    return ctx.app.emit('error', errorType, ctx);
  }

  // 3.判断用户名是否存在
  const result = await service.getUserByName(name);
  // console.log(result);     //拿到的是一个数组，数组中嵌套了一个对象，对象中是用户的id，name，password，createAt，updateAt信息
  const user = result[0];
  // console.log(result[0]);
  if (!user) {
    const errorType = new Error(errorTypes.USER_DOES_NOT_EXISTS);
    return ctx.app.emit('error', errorType, ctx);
  }

  // 4.验证密码是否正确
  // console.log(user.password);   //打印登录时加密后的密码
  if (md5password(password) !== user.password) {
    const errorType = new Error(errorTypes.PASSWORD_IS_INCORRENT);
    return ctx.app.emit('error', errorType, ctx);
  }

  ctx.user = user; //将user放入ctx中
  await next();
}





const verifyAuth = async (ctx, next) => {
  // console.log(ctx.headers);
  const authorization = ctx.headers.authorization; //在请求头ctx.headers中的authorization属性中拿到token令牌

  if (!authorization) { //判断一下这个属性中有没有token令牌，如果为反就代表没有
    console.log("ctx.app");
    const errorType = new Error(errorTypes.NOT_GET_TOKEN); //如果没有token令牌就抛出错误
    return ctx.app.emit('error', errorType, ctx);
  }
  const token = authorization.replace("Bearer ", ""); //因为拿到的token字符串前面有一个Bearer字符串和一个空格，所以需要截掉


  try { //使用try。。catch语句来捕捉错误,如果令牌没有通过验证，它就会报错，我们就可以使用try。。catch来捕捉这个错误
    const result = jwt.verify(token, PUBLIC_KEY, { //使用公钥进行解码
      algorithms: ["RS256"] //设置采用什么算法解码，要和上面加密的算法一致(注：数组中可以传入多种算法，如果不行，它会挨个挨个试)
    });
    // console.log(result);    //打印的内容：{ id: 2, name: '张瀚', iat: 1616639092, exp: 1616639192 }
    ctx.user = result; //将此用户的信息添加在ctx.user属性中，以便在后面的中间件中使用
    await next();

  } catch (err) {
    // console.log(err);
    const errorType = new Error(errorTypes.UNAUTHORIZATION);
    return ctx.app.emit('error', errorType, ctx);
  };
};




//这个中间件是拿到=来验证此用户是否有权限来删除或修改动态,评论等等
const verifyPermission = async (ctx, next) => {
  // console.log(ctx.params);     //打印:{ commentId: '1' }
  const [resourceKey] = Object.keys(ctx.params); //使用Obiject.keys方式从对象中拿到键值对的key,并使用数组的方式返回，所以我们对数组进行结构拿到数组中的key
  // console.log(resourceKey);     //打印：commentId
  const tableName = resourceKey.replace('Id', ''); //打印：comment
  // console.log(tableName);
  const resourceId = ctx.params[resourceKey]; //这里必须使用[resourceKey]，不能使用.resourceKey方式
  // console.log(resourceId);    //打印1
  const userId = ctx.user.id;
  // console.log(userId);

  try {
    const isPermission = await authService.checkResource(tableName, resourceId, userId);
    //  console.log(isPermission);
    if (!isPermission) throw new Error();
    await next();
  } catch (err) {
    const errorType = new Error(errorTypes.UNPERMISSION);
    return ctx.app.emit('error', errorType, ctx);
  }
};




//这个中间件是拿到=来验证此用户是否有权限来删除或修改动态,评论等等
//  const verifyPermission = (tableName) => {
//    return async (ctx, next) => {
//      const resourceId = ctx.request.params.commentId;
//      const userId = ctx.user.id;

//      try {
//        const isPermission = await authService.checkResource(tableName, resourceId, userId);
//       //  console.log(isPermission);
//        if (!isPermission) throw new Error();   
//        await next();
//      } catch (err) {
//        const errorType = new Error(errorTypes.UNPERMISSION);
//        return ctx.app.emit('error', errorType, ctx);
//      }   
//   };
//  }



module.exports = {
  verifyUser,
  verifyAuth,
  verifyPermission 
}